#pragma once
#include <iostream>
#include "Socket.hpp"
class SelectServer
{
private:
    static const int fd_num_max = (sizeof(fd_set) * 8);
    static const int fd_deafault = -1;
    void HandlerEvent(fd_set &set)
    {
        for (int j = 0; j < fd_num_max; j++)
        {
            int fd = fd_arry[j];
            if (fd == fd_deafault)
                continue;
            if (FD_ISSET(fd, &set))
            {
                if (fd == listen_socket_.ReturnSocketfd())
                {
                    // 如果监听到的是监听套接字的读事件说明有新链接来了
                    SocketInfo client_info;
                    listen_socket_.Accept(client_info);
                    if (client_info.socketfd_ < 0)
                        return;
                    // fd_arry[client_info.socketfd_]=client_info.socketfd_;端口可不止1024个
                    int i = 0;
                    for (i = 0; i < fd_num_max; i++)
                    {
                        if (fd_arry[i] != fd_deafault)
                            continue;
                        fd_arry[i] = client_info.socketfd_;
                        break;
                    }
                    if (i == fd_num_max)
                    {
                        lg.logmessage(Warning, "not enough location");
                        close(client_info.socketfd_);
                    }
                }
                else
                {
                    // 有人给我发消息
                    char buffer[1024*4];
                    int n=read(fd,buffer,sizeof(buffer));
                    if(n>0)
                    {
                        lg.logmessage(Info,"echo# %s",buffer);
                    }
                    else
                    {
                        close(fd);
                        fd_arry[j]=fd_deafault;
                    }
                }
            }
        }
    }

public:
    SelectServer(uint16_t port) : port_(port)
    {
    }

    void InIt()
    {
        listen_socket_.CreatSocket();
        listen_socket_.Bind(port_);
        listen_socket_.Listen();
        fd_arry[0] = listen_socket_.ReturnSocketfd();
        for (int i = 1; i < fd_num_max; i++)
        {
            fd_arry[i] = fd_deafault;
        }
    }

    void Start()
    {

        int listen_socket_fd = listen_socket_.ReturnSocketfd();
        for (;;)
        {
            fd_set set;
            FD_ZERO(&set); // 将位图置0
            int max_fd = fd_arry[0];
            for (int i = 0; i < fd_num_max; i++)
            {
                if (i == fd_deafault)
                    continue;
                FD_SET(fd_arry[i], &set);
                if (max_fd < fd_arry[i])
                {
                    max_fd = fd_arry[i];
                }
            }
            struct timeval timeout = {5, 0};                             // 5秒 0毫秒
            int n = select(max_fd + 1, &set, nullptr, nullptr, nullptr); // 最大文件描述符+1 监听读事件是否就绪  写 ？ 隔几秒监听一次
            std::cout << "....." << std::endl;
            switch (n)
            {
            case 0:
                lg.logmessage(Warning, "time out");
                break;
            case -1:
                lg.logmessage(Fatal, "select error %d:%s", errno, strerror(errno));
                break;
            default:
                // std::cout << "get ready" << std::endl;
                HandlerEvent(set);
                break;
            }
        }
    }

private:
    Socket listen_socket_;
    uint16_t port_;
    int fd_arry[fd_num_max] = {-1};
};
